package generation;

import java.util.ArrayList;

public class PasswordMemorisation {
	//return a value between 0 and 1, which correspond to the memorization fitness 
	public static float passwordMemorisation(String indivString, ArrayList<String> evaluatedIndiv) {
		ArrayList<Double> temp_inv_dist = new ArrayList<Double>();
		for(int i = 0; i < evaluatedIndiv.size(); i++) {
			double temp_dist = levenshteinDistance(indivString, evaluatedIndiv.get(i));
			if(temp_dist  == 0) {
				return 1;
			}
			else {
				temp_inv_dist.add(1/temp_dist);
			}
		}

		double weight_sum = 0;
		for(int i = 0; i < evaluatedIndiv.size(); i++) {
			weight_sum += temp_inv_dist.get(i);
		}

		float ponderate_weight_sum = 0;
		for(int i = 0; i < evaluatedIndiv.size(); i++) {
			float temp_fit = (float) (1/(1+temp_inv_dist.get(i)/3));
			ponderate_weight_sum += temp_inv_dist.get(i) * temp_fit / weight_sum;
		}
		
		return ponderate_weight_sum;
	}
	
	/*
	private static double myDistanceTo(String indiv1, String indiv2) {
		double count = 0.0;
		ArrayList<String> listLetter = new ArrayList<String>();
		 for(int i = 0; i<indiv2.length(); i++) {
			 listLetter.add(indiv2.substring(i,i+1));
		 }
		 for(int i = 0; i<indiv1.length(); i++) {
			 String currentLetter = indiv1.substring(i,i+1);
			 if(!listLetter.isEmpty()) {
				 if (listLetter.contains(currentLetter)) {
				 count ++;
				 listLetter.remove(currentLetter);
				 }
			 }
		 }
		 count -= indiv2.length();

		return (-count);
	}
	*/
	
	/**
	 * compute the Levenshtein distance between two strings
	 * @author Xavier Philippeau
	 * 
	 * @param s0 String 0
	 * @param s1 String 1
	 * @return the Levenshtein distance
	 */
	private static double levenshteinDistance(String s0, String s1) {
			int len0 = s0.length()+1;
			int len1 = s1.length()+1;
		 
			// the array of distances
			int[] cost = new int[len0];
			int[] newcost = new int[len0];
		 
			// initial cost of skipping prefix in String s0
			for(int i=0;i<len0;i++) cost[i]=i;
		 
			// dynamicaly computing the array of distances
		 
			// transformation cost for each letter in s1
			for(int j=1;j<len1;j++) {
		 
				// initial cost of skipping prefix in String s1
				newcost[0]=j-1;
		 
				// transformation cost for each letter in s0
				for(int i=1;i<len0;i++) {
		 
					// matching current letters in both strings
					int match = (s0.charAt(i-1)==s1.charAt(j-1))?0:1;
		 
					// computing cost for each transformation
					int cost_replace = cost[i-1]+match;
					int cost_insert  = cost[i]+1;
					int cost_delete  = newcost[i-1]+1;
		 
					// keep minimum cost
					newcost[i] = min(cost_insert, cost_delete, cost_replace);
				}
		 
				// swap cost/newcost arrays
				int[] swap=cost; cost=newcost; newcost=swap;
			}
		 
			// the distance is the cost for transforming all letters in both strings
			return cost[len0-1];
		}

		private static int min(int cost_insert, int cost_delete, int cost_replace) {
			int tempMin = cost_insert;
			if(tempMin > cost_delete)
				tempMin = cost_delete;
			if(tempMin > cost_replace)
				tempMin = cost_replace;
			return tempMin;
		}
}
